package com.dlc.shop.wukongim.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.dlc.shop.bean.dto.wukong.*;
import com.dlc.shop.bean.model.ImChannel;
import com.dlc.shop.bean.vo.wukong.ConversationSyncVO;
import com.dlc.shop.bean.vo.wukong.MessageSyncVO;
import com.dlc.shop.bean.vo.wukong.UserOnlineVO;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.enums.SysTypeEnum;
import com.dlc.shop.common.util.Json;
import com.dlc.shop.common.wukongim.constant.WuKongConstant;
import com.dlc.shop.wukongim.config.WuKongImConfig;
import com.dlc.shop.wukongim.service.WuKongImService;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author TRACK
 */
@Service
@AllArgsConstructor
public class WuKongImServiceImpl implements WuKongImService {
    private static final Logger logger = LoggerFactory.getLogger(WuKongImServiceImpl.class);

    private final WuKongImConfig wuKongImConfig;

    @Override
    public void registerOrLogin(RegisterOrLoginDTO registerOrLoginDTO) {
        wuKongImConfig.post(WuKongConstant.REGISTER_OR_LOGIN, registerOrLoginDTO);
    }

    @Override
    public List<Long> listOnlineManagerIds(List<Long> employeeIds, Long shopId) {
        Boolean isSys = Objects.equals(shopId, Constant.PLATFORM_SHOP_ID);
        List<String> uids = new ArrayList<>(employeeIds.size());
        for (Long shopEmployeeId : employeeIds) {
            if (isSys) {
                uids.add(WuKongConstant.getSysUid(shopEmployeeId));
            } else {
                uids.add(WuKongConstant.getShopUid(shopEmployeeId, shopId));
            }
        }
        List<UserOnlineVO> onlineUids = JSON.parseArray(JSON.toJSONString(wuKongImConfig.post(WuKongConstant.ONLINE_STATUS, uids, List.class)),
                UserOnlineVO.class);
        Set<Long> onlineShopEmployeeIds = new HashSet<>(onlineUids.size());
        for (UserOnlineVO onlineUid : onlineUids) {
            if (!Objects.equals(onlineUid.getOnline(), 1)) {
                continue;
            }
            String uid = onlineUid.getUid();
            if (isSys) {
                onlineShopEmployeeIds.add(WuKongConstant.getSysUserId(uid));
            } else {
                onlineShopEmployeeIds.add(WuKongConstant.getEmployeeId(uid));
            }
        }
        return new ArrayList<>(onlineShopEmployeeIds);
    }

    @Override
    public Boolean getUserOnline(String uid) {
        List<UserOnlineVO> onlineUids = JSON.parseArray(JSON.toJSONString(wuKongImConfig.post(WuKongConstant.ONLINE_STATUS, Collections.singletonList(uid), List.class)),
                UserOnlineVO.class);
        Set<String> onlineUidSet = onlineUids.stream().filter(onlineUid -> Objects.equals(onlineUid.getOnline(), 1)).map(UserOnlineVO::getUid).collect(Collectors.toSet());
        return CollUtil.isNotEmpty(onlineUidSet);
    }

    @Override
    public void addSubscriber(String channelId, String uid) {
        SubscriberAddDTO subscriberAddDTO = new SubscriberAddDTO(channelId, Collections.singletonList(uid));
        wuKongImConfig.post(WuKongConstant.SUBSCRIBER_ADD, subscriberAddDTO);
    }

    @Override
    public void removeSubscriber(String channelId, String uid) {
        SubscriberRemoveDTO subscriberRemoveDTO = new SubscriberRemoveDTO(channelId, Collections.singletonList(uid));
        wuKongImConfig.post(WuKongConstant.SUBSCRIBER_REMOVE, subscriberRemoveDTO);
    }

    @Override
    public void sendTransferMessage(String channelId, String nickName, String uid) {
        HeaderDTO headerDTO = new HeaderDTO(0, 1, 0);
        MessageSendDTO messageSendDTO = new MessageSendDTO(headerDTO, uid, channelId);
        String content = nickName + "为您服务";
        PayloadDTO payload = new PayloadDTO(1, Json.toJsonString(new TransMsgDTO(-5, content, 1)));
        messageSendDTO.setPayload(Base64.encode(Json.toJsonString(payload)));
        wuKongImConfig.post(WuKongConstant.MESSAGE_SEND, messageSendDTO);
    }

    @Override
    public void sendReadMessage(String channelId, Long maxSeq, Integer userType) {
        if (Objects.isNull(maxSeq)) {
            return;
        }
        HeaderDTO headerDTO = new HeaderDTO(1, 0, 1);
        MessageSendDTO messageSendDTO = new MessageSendDTO(headerDTO, WuKongConstant.SYSTEM_UID, channelId);
        // -2 用户已读消息 -3 商家已读消息
        Integer type = Objects.equals(userType, SysTypeEnum.ORDINARY.value()) ? -2 : -3;
        PayloadDTO payload = new PayloadDTO(99, Json.toJsonString(new PayloadDTO(type, maxSeq.toString())));
        messageSendDTO.setPayload(Base64.encode(Json.toJsonString(payload)));
        wuKongImConfig.post(WuKongConstant.MESSAGE_SEND, messageSendDTO);
    }

    @Override
    public void sendAutoReplyMessage(String channelId, String content, String uid) {
        HeaderDTO headerDTO = new HeaderDTO(0, 1, 0);
        MessageSendDTO messageSendDTO = new MessageSendDTO(headerDTO, uid, channelId);
        PayloadDTO payload = new PayloadDTO(1, content);
        messageSendDTO.setPayload(Base64.encode(Json.toJsonString(payload)));
        wuKongImConfig.post(WuKongConstant.MESSAGE_SEND, messageSendDTO);
    }

    @Override
    public void sendLiveRoomMessage(String channelId, String content, String uid) {
        HeaderDTO headerDTO = new HeaderDTO(1, 0, 0);
        MessageSendDTO messageSendDTO = new MessageSendDTO(headerDTO, WuKongConstant.SYSTEM_UID, channelId);
        if (Objects.nonNull(uid) && StrUtil.isNotBlank(uid)) {
            messageSendDTO.setSubscribers(Collections.singletonList(uid));
        }
        PayloadDTO payload = new PayloadDTO(1, content);
        messageSendDTO.setPayload(Base64.encode(Json.toJsonString(payload)));
        wuKongImConfig.post(WuKongConstant.MESSAGE_SEND, messageSendDTO);
    }

    @Override
    public void createChannel(ChannelDTO channelDTO) {
        wuKongImConfig.post(WuKongConstant.CHANNEL_CREATE, channelDTO);
    }

    @Override
    public void deleteChannel(ChanneDeleteDTO channeDeleteDTO) {
        wuKongImConfig.post(WuKongConstant.CHANNEL_DELETE, channeDeleteDTO);
    }

    @Override
    public List<ConversationSyncVO> conversationSync(ConversationSyncDTO conversationSyncDTO) {
        return JSON.parseArray(JSON.toJSONString(wuKongImConfig.post(WuKongConstant.CONVERSATION_SYNC, conversationSyncDTO, List.class)),
                ConversationSyncVO.class);
    }

    @Override
    public void setUnread(SetUnreadDTO setUnreadDTO) {
        wuKongImConfig.post(WuKongConstant.SET_UNREAD, setUnreadDTO);
    }

    @Override
    public void deviceQuit(RegisterOrLoginDTO registerOrLoginDTO) {
        wuKongImConfig.post(WuKongConstant.DEVICE_QUIT, registerOrLoginDTO);
    }

    @Override
    public MessageSyncVO messageSync(MessageSyncDTO messageSyncDTO) {
        return wuKongImConfig.post(WuKongConstant.MESSAGE_SYNC, messageSyncDTO, MessageSyncVO.class);
    }

    @Override
    public void messageSendbatch(String payload, List<String> channelIds, String cmd) {
        List<String> uids = new ArrayList<>(channelIds.size());
        channelIds.forEach(channelId -> {
            uids.add(WuKongConstant.getUid(channelId));
        });
        Set<String> onlineChannelSet = new HashSet<>(channelIds.size());
        if (Objects.equals(cmd, WuKongConstant.ONLINE_UPDATE)) {
            List<UserOnlineVO> onlineUids = JSON.parseArray(JSON.toJSONString(wuKongImConfig.post(WuKongConstant.ONLINE_STATUS, uids, List.class)),
                    UserOnlineVO.class);
            Set<String> onlineUidSet = onlineUids.stream().filter(uid -> Objects.equals(uid.getOnline(), 1)).map(UserOnlineVO::getUid).collect(Collectors.toSet());
            // 只给在线的用户发送消息
            if (onlineUidSet.isEmpty()) {
                return;
            }
            for (String channelId : channelIds) {
                String userId = WuKongConstant.getUid(channelId);
                if (onlineUidSet.contains(userId)) {
                    onlineChannelSet.add(channelId);
                }
            }
        } else {
            onlineChannelSet.addAll(channelIds);
        }
        HeaderDTO headerDTO = new HeaderDTO(1, 0, 1);
        for (String onlineChannel : onlineChannelSet) {
            MessageSendDTO messageSendDTO = new MessageSendDTO(headerDTO, WuKongConstant.SYSTEM_UID, onlineChannel);
            PayloadDTO payloadDTO = new PayloadDTO(99, cmd, payload);
            messageSendDTO.setPayload(Base64.encode(Json.toJsonString(payloadDTO)));
            if (Objects.equals(cmd, WuKongConstant.ONLINE_UPDATE)) {
                messageSendDTO.setSubscribers(Collections.singletonList(WuKongConstant.getUid(onlineChannel)));
            }
            wuKongImConfig.post(WuKongConstant.MESSAGE_SEND, messageSendDTO);
        }
    }

    @Override
    public void userMessageSendbatch(String userId, List<String> uids, List<ImChannel> imChannels) {
        List<UserOnlineVO> onlineUids = JSON.parseArray(JSON.toJSONString(wuKongImConfig.post(WuKongConstant.ONLINE_STATUS, uids, List.class)),
                UserOnlineVO.class);
        Set<String> onlineUidSet = onlineUids.stream().filter(uid -> Objects.equals(uid.getOnline(), 1)).map(UserOnlineVO::getUid).collect(Collectors.toSet());
        // 只给在线的用户发送消息
        if (onlineUidSet.isEmpty()) {
            return;
        }
        Set<String> onlineChannelSet = new HashSet<>(onlineUidSet.size());
        for (ImChannel imChannel : imChannels) {
            String uid;
            if (Objects.equals(imChannel.getShopId(), Constant.PLATFORM_SHOP_ID)) {
                uid = WuKongConstant.getSysUid(imChannel.getEmployeeId());
            } else {
                uid = WuKongConstant.getShopUid(imChannel.getEmployeeId(), imChannel.getShopId());
            }
            if (onlineUidSet.contains(uid)) {
                onlineChannelSet.add(imChannel.getChannelId());
            }
        }
        HeaderDTO headerDTO = new HeaderDTO(1, 0, 1);
        for (String onlineChannel : onlineChannelSet) {
            MessageSendDTO messageSendDTO = new MessageSendDTO(headerDTO, WuKongConstant.SYSTEM_UID, onlineChannel);
            PayloadDTO payloadDTO = new PayloadDTO(99, WuKongConstant.USER_DESTROY, onlineChannel);
            messageSendDTO.setPayload(Base64.encode(Json.toJsonString(payloadDTO)));
            wuKongImConfig.post(WuKongConstant.MESSAGE_SEND, messageSendDTO);
        }
    }

    @Override
    public void sendChangeUserInfoMessage(String channelId) {
        HeaderDTO headerDTO = new HeaderDTO(1, 0, 1);
        MessageSendDTO messageSendDTO = new MessageSendDTO(headerDTO, WuKongConstant.SYSTEM_UID, channelId);
        PayloadDTO payload = new PayloadDTO(99, WuKongConstant.MEMBER_UPDATE, channelId);
        messageSendDTO.setPayload(Base64.encode(Json.toJsonString(payload)));
        wuKongImConfig.post(WuKongConstant.MESSAGE_SEND, messageSendDTO);
    }

    @Override
    public void sendDeleteUnreadInfoMessage(String channelId, Integer userType) {
        Integer sender = 1;
        if (Objects.equals(userType, SysTypeEnum.ORDINARY.value())) {
            sender = 0;
        }
        HeaderDTO headerDTO = new HeaderDTO(1, 0, 1);
        MessageSendDTO messageSendDTO = new MessageSendDTO(headerDTO, WuKongConstant.SYSTEM_UID, channelId);
        PayloadDTO payload = new PayloadDTO(99, WuKongConstant.UNREAD_CLEAR, Json.toJsonString(new TransMsgDTO(-6, channelId, sender)));
        messageSendDTO.setPayload(Base64.encode(Json.toJsonString(payload)));
        wuKongImConfig.post(WuKongConstant.MESSAGE_SEND, messageSendDTO);
    }
}
